package toy.keli.edic.ui.home

import android.util.Log
import androidx.compose.runtime.MutableState
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import toy.keli.edic.data.Db
import toy.keli.edic.data.GlobalVal
import toy.keli.edic.data.config.BookConf
import toy.keli.edic.data.config.MenuConf
import toy.keli.edic.data.local.entity.DictionaryEntity
import toy.keli.edic.data.local.entity.DictionarySubEntity
import toy.keli.edic.data.model.Article
import toy.keli.edic.data.model.Category
import toy.keli.edic.data.model.Query
import toy.keli.edic.data.model.WordExtend
import toy.keli.edic.domain.model.WordModel
import toy.keli.edic.domain.repository.DictionaryBaseRepository
import toy.keli.edic.domain.repository.WordBaseRepository
import toy.keli.edic.ui.history.HistoryViewModel
import toy.keli.edic.ui.home.components.OverJump
import toy.keli.edic.ui.main.components.InfoDialog
import toy.keli.edic.ui.navigation.NavScreen
import toy.keli.edic.util.NetDicUtil
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.launch
import toy.keli.edic.data.local.WordModelDao
import toy.keli.edic.data.repository.DictionaryRepository
import toy.keli.edic.data.repository.WordRepository
import toy.keli.edic.ui.main.extend.MainRun
import java.text.SimpleDateFormat
import java.util.Date
import javax.inject.Inject
import toy.keli.edic.ui.main.extend.commonPrefixLengthWith

@HiltViewModel
class WordModelViewModel @Inject constructor(
    private val wordRepo: WordBaseRepository,
    private val dictRepository: DictionaryBaseRepository
) : ViewModel() {

    var wordState = MutableStateFlow(WordState())
        private set

    var suggestions = MutableStateFlow(emptyList<String>())
        private set

    var detailState = MutableStateFlow(false)

    var selectLevel = MutableStateFlow(-1)
        private set
    private var workIndex = -1

    // 缓存当前字段单词和WordSetId
    private val currentDictionarySub = MutableStateFlow(DictionarySubEntity.empty())
    val currentDictionary = MutableStateFlow(DictionaryEntity(null, "", "", "", -1))

    private var searchJob: Job? = null
    private var prefixMatchJob: Job? = null

    fun initByLevel(level: Int) {
        if (level > -1) {
            viewModelScope.launch(IO) {
                Log.d(TAG, "initByLevel() level = $level")
                dictRepository.getWordSetInCacheByLevel(level).firstOrNull()
            }
        }
        selectLevel.value = level
    }

    fun changeLevelAndGetNewRandomDictionary(level: Int,index:Int=-1) {
        if (level > -1) {
            viewModelScope.launch(IO) {
                Log.d(TAG, "changeLevelAndGetNewRandomDictionary() level = $level")
                dictRepository.getWordSetInCacheByLevel(level).firstOrNull()
                setWordState(index)
                selectLevel.value = level
            }
        }
    }

    fun setWord(it: DictionarySubEntity) {
        currentDictionarySub.value = it
        wordState.value = WordState(it.toWordModel())
        detailState.value = false
    }
    private fun setWordState(i:Int = -1): WordState {
            var index = i
            val randIndex = dictRepository.randomCacheSubEntityIdx()
            if(index == -1 || randIndex == -1) {
                index = randIndex
                if (index == -1) return wordState.value
            }else{
                index = dictRepository.getWorkIndex(0-index)
                //搜索之前 查询了一次从列表里删除了
                if(index == -1) index = randIndex
            }

            val size = dictRepository.size()
            if(index>size) return wordState.value
            Log.d(TAG, "Index = $i $randIndex $index/$size")
            workIndex = dictRepository.getWorkIndex(index)
            dictRepository.getCacheSubEntity(index)?.let {
                currentDictionarySub.value = it
                wordState.value = WordState(it.toWordModel())
                detailState.value = false
            } ?: DictionarySubEntity.empty()
        return wordState.value
    }


    fun searchByText() {
        searchJob?.cancel()
        val current = currentDictionarySub.value.word
        searchJob = viewModelScope.launch(IO) {
            val result = dictRepository.search(current).firstOrNull()?.first()
                ?: DictionaryEntity.emptyDictionary()
            currentDictionary.value = result
            wordState.value = WordState(result.toWordModel())
            if(result.word.length>0) {
                detailState.value = true
            }
        }
    }

    fun searchByWordSetId() {
        searchJob?.cancel()
        val wordSetId = currentDictionarySub.value.wordsetId
        searchJob = viewModelScope.launch(IO) {
            val result = dictRepository.search(wordSetId).firstOrNull()?.first()
            currentDictionary.value = result ?: DictionaryEntity.emptyDictionary()
        }
    }

    fun nextDictionaryWord() {
        viewModelScope.launch(IO) {
            val index = dictRepository.randomCacheSubEntityIdx()
            Log.d(TAG, "Index = $index")
            dictRepository.getCacheSubEntity(index)?.let {
                currentDictionarySub.value = it
                wordState.value = WordState(it.toWordModel())
                detailState.value = false
            } ?: DictionarySubEntity.empty()
        }
    }


    fun prefixMatcher(query: String,searchWords:Boolean=true,onNoMatch:()->Unit={},onSugOver:(MutableStateFlow<List<String>>.(List<String>)->Unit)?=null,onMatch:(word:String)->Boolean={ false }) {
        clearSuggestions()
        prefixMatchJob?.cancel()
        prefixMatchJob = viewModelScope.launch(IO) {
            if (!searchWords || query.startsWith(":")) {
                val queryKey = if(searchWords)  query.substring(1) else query;
                val sugs = arrayListOf<String>()
                val aQuery = Article.self.query.like("name",queryKey).build()
                val cQuery = Category.self.query.like("name",queryKey).build()
                val lQuery = Query(Db.dictionary,"levelTable").like("name",queryKey).build()
                val a = Db.user.article.select(aQuery).map { "article.${it.id}:${it.name}" }
                val c = Db.user.category.select(cQuery).map { "category.${it.id}:${it.name}" }
                val l = Db.dictionary.levelDao.select(lQuery).map { "level.${it.id}:${it.name}" }
                sugs.addAll(a); sugs.addAll(c); sugs.addAll(l)
                suggestions.value = sugs
                if(onSugOver!=null) onSugOver.invoke(suggestions,sugs)

            } else  if(query.matches(Regex("[\u4E00-\u9FA5]+"))) {
                dictRepository.searchByCh(query).collect { matches ->
                    suggestions.value = matches.map{ it.word+":"+it.ch}
                    if(onSugOver!=null) onSugOver.invoke(suggestions,suggestions.value)
                }
            }else{
                val queryObj = Query(Db.user, "historyTable").like("word", query).limit(1000).build()
                val historyMap = Db.user.wordModelDao.getHistoryList(queryObj).map {
                    val date = SimpleDateFormat("MM月dd日HH点").format(Date(it.time))
                    var ch = if(it.ch!=null) it.ch?.take(4) else ""
                    it.word to "${it.word} : ${ch}(${date})"
                }.toMap().toSortedMap();
                dictRepository.prefixMatch(query).onCompletion {
                    //搜索完成之后

                }.collect { match ->
                        val sublist = match.map {
                            //单词匹配之后就直接返回 不要再显示sug了
                            if (it.word == query.toLowerCase()) {
                                HomeEvents.searchTools.onPreMatcheMathchOk(it.word,onMatch)?.let { suggestions.value = it }
                                return@collect
                            }
                            it.word+" : "+ (if(it.ch!=null) it.ch.take(10) else "")
                        }
                        onNoMatch();
                        suggestions.value = sublist
                        //存在历史历史排序在前面
                        if(historyMap.size>0) {
                            val suggerMeragesData = arrayListOf<String>()
                            //前面的历史数据
                            suggerMeragesData.addAll(historyMap.values.sortedByDescending {
                                it.commonPrefixLengthWith(query)
                            })
                            //去重后的搜索数据
                            suggerMeragesData.addAll(sublist.filter { !historyMap.containsKey(it.replace(Regex(" : .+"),"")) })
                            suggestions.value = suggerMeragesData
                        }
                        if(suggestions.value.size==0 && query.length>0){
                            wordState.value = WordState(null)
                            HomeEvents.searchTools.onSuggestEmpty(query,onMatch)?.let{
                                suggestions.value = it
                            }
                        }
                    if(onSugOver!=null) onSugOver.invoke(suggestions,suggestions.value)

                }
            }
        }
    }


    fun searcher(query: String, isWordClick: Boolean = false) {
        if (query.isBlank()) {
            clearSuggestions()
            return
        }
        searchJob?.cancel()
        searchJob = viewModelScope.launch(IO) {
            if(query.indexOf(":") > 0){
                val v = query.split(Regex("[:\\.]+"))
                val key =v.first()
                val id = if(v[1].length<10) v[1].toInt() else 0
                val value = v.last()
                when(key){
                    "level" -> {
//                        changeLevelAndGetNewRandomDictionary(id)
                        NavScreen.openHome(PAGE_FROM_LEVEL,0,id)
                    }
                    "bookmark" -> {
                        NavScreen.BookmarkScreen.open();
                    }
                    "history" ->{
                        HistoryViewModel.searchDay(value)
                        NavScreen.openHome(PAGE_FROM_HISTORY)
                    }
                    "article" ->{
                        BookConf.setBook(id)
                        NavScreen.openHome(PAGE_FROM_BOOKMARK)
                    }
                    "category" ->{
                        Category.getArticles(id, true) {
                            val rt = arrayListOf<String>()
                            it.forEach {
                                rt.addAll(it.findWords())
                            }
                            GlobalVal.bookmarkViewModel.upListByWords(rt) {
                                NavScreen.openHome(PAGE_FROM_BOOKMARK)
                            }
                        }
                    }
                }
                return@launch
            }
            val result = dictRepository.search(query).firstOrNull()?.first()
            result?.let {
                wordState.value = WordState(it.toWordModel())
                currentDictionary.value = DictionaryEntity(it.meanings,it.word,it.wordsetId,it.ch,it.level)
                currentDictionarySub.value = DictionarySubEntity(word = it.word, wordsetId = it.wordsetId, level = it.level)
                BookConf.instance.next(wordState.value.wordModel!!)
                if (isWordClick) insertHistory(it.toWordModel())
            }
        }
    }

    fun clearSuggestions() {
        suggestions.value = emptyList()
    }
    //是否在保存的记录中
    suspend fun isInBookmark() :Boolean{
        val word = wordState.value.wordModel?.word;
        if(word!=null) {
            val rt = Db.user.wordModelDao.findBookmarkByWord(word).firstOrNull();
            if(rt!=null) return true;
        }
        return false;
    }
    fun insertBookmark(wordModel: WordModel) {
        viewModelScope.launch(IO) {
            wordRepo.insertBookmark(wordModel.toBookmarkEntity())
        }
    }

    fun insertHistory(wordModel: WordModel) {
        viewModelScope.launch(IO) {
            try {
                wordRepo.insertHistory(wordModel.toHistoryEntity())
            }catch (e:Exception){
                e.printStackTrace()
            }
        }
    }

    /**
     * 显示下一个
     * uOrder 不要排序无序的
     * detailShow 显示详情
     */
    fun showNext(uOrder: Boolean,detailShow:Boolean = false) {
        if(dictRepository.size()>0) {
            var index = dictRepository.randomCacheSubEntityIdx()
            if(index<0) {
                //ActivityRun.msg("已经是最后一个了")
                InfoDialog.show{
                    OverJump()
                }
                return
            }
            if(!uOrder) index =0
            //workIndex = dictRepository.getWorkIndex(index)
            dictRepository.getCacheSubEntity(index)?.let {
                currentDictionarySub.value = it
                wordState.value = WordState(it.toWordModel())
                BookConf.instance.index++
                BookConf.instance.next(wordState.value.wordModel!!)
            } ?: DictionarySubEntity.empty()

            detailState.value = detailShow
        }else{
            InfoDialog.show{
                OverJump()
            }
        }
    }
    fun cacheSub():List<WordModel>{
        return dictRepository.getWords()
    }

    fun upList(wordModelList: List<WordModel>) {
        var wordList = if(BookConf.instance.index+1 == wordModelList.size || wordModelList.size==0) arrayListOf<WordModel>() else wordModelList.subList(BookConf.instance.index+1,wordModelList.size)
        dictRepository.setWords(wordList)
//        setWordState(0)
    }



    companion object {
        const val TAG = "WordModelViewModel"
        val defaultStatus:WordState = WordState(WordModel(null, "abc", "0", 0))
        val defaultModel:WordModelViewModel = WordModelViewModel(WordRepository(wordModelDao = Db.user.wordModelDao),DictionaryRepository(Db.dictionary.dictionaryDao,Db.dictionary.levelDao,Db.user.wordModelDao)).apply {
                wordState.value = defaultStatus
        }
    }
}